package com.example.lab.controller;

import com.example.lab.entity.User;
import com.example.lab.entity.dto.LoginRequest;
import com.example.lab.result.Result;
import com.example.lab.service.impl.UserServiceImpl;
import com.example.lab.util.JwtTokenUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;


/**
 *@Author: 布莱恩
 *@Date: 2025/6/16 23:57
 *@Description:
 **/
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {

    private final AuthenticationManager authenticationManager;
    private final UserServiceImpl userService;
    private final JwtTokenUtil jwtTokenUtil;

    /**
     * 处理登录请求的控制器方法
     * 该方法接收一个LoginRequest对象作为参数，其中包含用户的登录信息（用户名和密码）
     * 使用@PostMapping注解限定该方法仅响应POST请求
     *
     * @param request 包含用户名和密码的登录请求对象
     * @return 返回一个Result对象，其中包含登录结果信息
     */
    @PostMapping("/login")
    public Result<String> login(@RequestBody LoginRequest request) {
        try {
            // 尝试通过用户名和密码认证用户
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            request.getUsername(),
                            request.getPassword()));

            // 认证成功后，将认证信息保存到SecurityContextHolder中
            SecurityContextHolder.getContext().setAuthentication(authentication);
            // 根据用户名加载用户详细信息
            UserDetails userDetails = userService.loadUserByUsername(request.getUsername());
            // 使用用户详细信息生成JWT令牌
            String jwt = jwtTokenUtil.generateToken(userDetails);

            // 返回登录成功结果，包含生成的JWT令牌
            return Result.success(jwt);
        } catch (BadCredentialsException e) {
            // 如果认证失败（用户名或密码错误），返回登录失败结果
            return Result.fail("用户名或密码错误");
        }
    }

    /**
     * 获取当前登录用户信息
     *
     * 该方法通过Spring Security的@AuthenticationPrincipal注解获取当前认证通过的用户信息
     * 主要用于在前端页面展示用户信息，如用户名、角色等
     *
     * @param userDetails 当前登录的用户对象，由Spring Security框架提供
     * @return 返回一个Result对象，其中包含用户信息
     */
    @GetMapping("/current-user")
    public Result<User> getCurrentUser(@AuthenticationPrincipal UserDetails userDetails) {

        // 1. 检查用户是否登录
        if (userDetails == null) {
            return Result.fail(401, "用户未登录");
        }

        // 2. 通过用户名查询完整用户信息
        User user = userService.getUserWithRolesAndPermissions(userDetails.getUsername());
        if (user == null) {
            return Result.fail(404, "用户不存在");
        }

        // 3. 返回用户信息
        return Result.success(user);

    }

}
